<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram</title>
</head>
<body>
<canvas id="physicsCanvas" width="600" height="480" style="border:1px solid #d3d3d3;"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Helper function to draw an arrow
    function drawArrow(ctx, fromX, fromY, toX, toY, headLength = 10) {
        const dx = toX - fromX;
        const dy = toY - fromY;
        const angle = Math.atan2(dy, dx);
        ctx.beginPath();
        ctx.moveTo(fromX, fromY);
        ctx.lineTo(toX, toY);
        ctx.moveTo(toX, toY);
        ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(toX, toY);
        ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }

    // Helper function to draw a double-headed arrow like a dimension line
    function drawDoubleHeadedArrow(ctx, x1, y1, x2, y2, headLength = 8) {
        const angle = Math.atan2(y2 - y1, x2 - x1);
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        // Head at x1
        ctx.moveTo(x1, y1);
        ctx.lineTo(x1 + headLength * Math.cos(angle + Math.PI - Math.PI/6), y1 + headLength * Math.sin(angle + Math.PI - Math.PI/6));
        ctx.moveTo(x1, y1);
        ctx.lineTo(x1 + headLength * Math.cos(angle + Math.PI + Math.PI/6), y1 + headLength * Math.sin(angle + Math.PI + Math.PI/6));
        // Head at x2
        ctx.moveTo(x2, y2);
        ctx.lineTo(x2 - headLength * Math.cos(angle - Math.PI/6), y2 - headLength * Math.sin(angle - Math.PI/6));
        ctx.moveTo(x2, y2);
        ctx.lineTo(x2 - headLength * Math.cos(angle + Math.PI/6), y2 - headLength * Math.sin(angle + Math.PI/6));
        ctx.stroke();
    }

    // --- Configuration ---
    const O = { x: 50, y: 420 };
    const O_prime = { x: 140, y: 420 };
    const R_pixels = 120;
    const circleCenter = { x: O_prime.x + R_pixels, y: O.y - R_pixels }; // (260, 300)
    
    ctx.lineWidth = 1.5;
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    // --- Draw S-frame ---
    ctx.font = 'italic 22px Times New Roman';
    // y-axis
    drawArrow(ctx, O.x, O.y, O.x, 50);
    ctx.fillText('y', O.x - 25, 50);
    // x-axis
    drawArrow(ctx, O.x, O.y, 560, O.y);
    ctx.fillText('x', 480, O.y + 20);
    ctx.fillText('O', O.x - 15, O.y + 15);
    
    ctx.font = '22px "SimSun", "Times New Roman"';
    ctx.fillText('S系', 85, 250);

    // --- Draw S'-frame ---
    ctx.font = 'italic 22px Times New Roman';
    // y'-axis
    drawArrow(ctx, O_prime.x, O_prime.y, O_prime.x, 50);
    ctx.fillText("y'", O_prime.x + 25, 50);
    // x'-axis label
    ctx.fillText("x'", 510, O.y + 20);
    ctx.fillText("O'", O_prime.x - 5, O_prime.y + 15);
    
    ctx.font = '22px "SimSun", "Times New Roman"';
    ctx.fillText("S'系", O_prime.x + 50, 250);
    
    // --- Draw Circle ---
    ctx.beginPath();
    ctx.arc(circleCenter.x, circleCenter.y, R_pixels, 0, 2 * Math.PI);
    ctx.stroke();

    // --- Draw Dashed Lines and Center ---
    ctx.save();
    ctx.setLineDash([5, 5]);
    ctx.strokeStyle = '#333';
    // Vertical line
    ctx.beginPath();
    ctx.moveTo(circleCenter.x, O.y);
    ctx.lineTo(circleCenter.x, circleCenter.y - R_pixels);
    ctx.stroke();
    // Horizontal line
    ctx.beginPath();
    ctx.moveTo(O_prime.x, circleCenter.y);
    ctx.lineTo(circleCenter.x, circleCenter.y);
    ctx.stroke();
    ctx.restore();
    
    // Center dot
    ctx.beginPath();
    ctx.arc(circleCenter.x, circleCenter.y, 4, 0, 2 * Math.PI);
    ctx.fill();

    // --- Draw Labels R ---
    ctx.font = 'italic 22px Times New Roman';
    ctx.fillText('R', circleCenter.x, O.y + 20);
    ctx.fillText('R', O_prime.x - 20, circleCenter.y);
    
    // --- Draw Particles P1 and P2 ---
    const topOfCircle = { x: circleCenter.x, y: circleCenter.y - R_pixels };
    const particleOffset = 10;
    const p1 = { x: topOfCircle.x - particleOffset, y: topOfCircle.y };
    const p2 = { x: topOfCircle.x + particleOffset, y: topOfCircle.y };
    
    // Dots
    ctx.beginPath();
    ctx.arc(p1.x, p1.y, 4, 0, 2 * Math.PI);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(p2.x, p2.y, 4, 0, 2 * Math.PI);
    ctx.fill();

    // Labels
    ctx.font = 'italic 22px Times New Roman';
    ctx.fillText('P', p1.x, p1.y + 25);
    ctx.fillText('P', p2.x, p2.y + 25);
    ctx.font = 'italic 16px Times New Roman';
    ctx.fillText('1', p1.x + 8, p1.y + 30);
    ctx.fillText('2', p2.x + 8, p2.y + 30);

    // --- Draw Particle Velocities ---
    const dimLineY = topOfCircle.y - 25;
    ctx.font = 'italic 22px Times New Roman';
    ctx.lineWidth = 1.5;

    // For 3v
    drawDoubleHeadedArrow(ctx, O_prime.x, dimLineY, circleCenter.x, dimLineY);
    ctx.fillText('3v', (O_prime.x + circleCenter.x) / 2, dimLineY - 15);

    // For v
    drawDoubleHeadedArrow(ctx, circleCenter.x, dimLineY, circleCenter.x + 80, dimLineY);
    ctx.fillText('v', (circleCenter.x + circleCenter.x + 80) / 2, dimLineY - 15);
    
    // --- Draw Frame Velocity ---
    const frameVelY = circleCenter.y;
    drawArrow(ctx, circleCenter.x + R_pixels + 20, frameVelY, circleCenter.x + R_pixels + 90, frameVelY);
    ctx.fillText('v', circleCenter.x + R_pixels + 55, frameVelY - 15);
    
    // Draw the second frame velocity arrow at the bottom right as in the image
    const vArrowBottomX = 400;
    const vArrowBottomY = O.y - 40; 
    drawArrow(ctx, vArrowBottomX, vArrowBottomY, vArrowBottomX + 70, vArrowBottomY);
    
</script>
</body>
</html>